{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "b0f38357",
   "metadata": {},
   "source": [
    "## 模型 (LLMs) 的类似少样本提示示例\n",
    "\n",
    "\n",
    "大模型是一种基于大量数据训练的人工智能模型，具有强大的下游任务自适应能力。相对于传统的人工智能模型，大模型可以处理更多的领域和任务，其优势主要体现在以下几个方面：\n",
    "1. 参数规模大：大模型拥有上亿甚至千亿级的参数，这使得它们可以处理更加复杂和抽象的任务，具有更强的泛化能力。\n",
    "2. 数据依赖性：大模型的训练依赖于大量的数据，这些数据覆盖了各种场景和情况，使得大模型能够更好地理解和处理各种复杂的问题。\n",
    "3. 适应性强：大模型可以适应各种不同的任务和领域，只需要通过少量的样本进行微调，就可以达到很好的效果。\n",
    "\n",
    "对于少量样本的提示，大模型具有以下优势：\n",
    "1. 快速适应：大模型具有很强的泛化能力，少量样本的提示可以使其快速适应新的任务和领域。\n",
    "2. 提高准确度：少量样本的提示可以减少模型的过拟合风险，提高模型的准确度。\n",
    "3. 节省资源：相对于重新训练模型，少量样本的提示可以节省大量的计算资源和时间。\n",
    "综上所述，少量样本的提示对于大模型的回答的准确度具有很大的优势，可以提高模型的适应性和准确度，同时节省资源。\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "8970b97b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts.few_shot import FewShotPromptTemplate\n",
    "from langchain.prompts.prompt import PromptTemplate\n",
    "\n",
    "examples = [\n",
    "    {\n",
    "        \"question\": \"乾隆和曹操谁活得更久?\",\n",
    "        \"answer\": \"\"\"\n",
    "这里是否需要跟进问题：是的。\n",
    "追问：乾隆去世时几岁？\n",
    "中间答案：乾隆去世时87岁。\n",
    "追问：曹操去世时几岁？\n",
    "中间答案：曹操去世时66岁。\n",
    "所以最终答案是：乾隆\n",
    "\"\"\",\n",
    "    },\n",
    "    {\n",
    "        \"question\": \"小米手机的创始人什么时候出生?\",\n",
    "        \"answer\": \"\"\"\n",
    "这里是否需要跟进问题：是的。\n",
    "追问：小米手机的创始人是谁？\n",
    "中间答案：小米手机 由 雷军 创立。\n",
    "跟进：雷军什么时候出生？\n",
    "中间答案：雷军出生于 1969 年 12 月 16 日。\n",
    "所以最终的答案是：1969 年 12 月 16 日\n",
    "\"\"\",\n",
    "    },\n",
    "    {\n",
    "        \"question\": \"乔治·华盛顿的外祖父是谁？\",\n",
    "        \"answer\": \"\"\"\n",
    "这里是否需要跟进问题：是的。\n",
    "追问：乔治·华盛顿的母亲是谁？\n",
    "中间答案：乔治·华盛顿的母亲是玛丽·鲍尔·华盛顿。\n",
    "追问：玛丽·鲍尔·华盛顿的父亲是谁？\n",
    "中间答案：玛丽·鲍尔·华盛顿的父亲是约瑟夫·鲍尔。\n",
    "所以最终答案是：约瑟夫·鲍尔\n",
    "\"\"\",\n",
    "    },\n",
    "    {\n",
    "        \"question\": \"《大白鲨》和《皇家赌场》的导演是同一个国家的吗？\",\n",
    "        \"answer\": \"\"\"\n",
    "这里是否需要跟进问题：是的。\n",
    "追问：《大白鲨》的导演是谁？\n",
    "中间答案：《大白鲨》的导演是史蒂文·斯皮尔伯格。\n",
    "追问：史蒂文·斯皮尔伯格来自哪里？\n",
    "中间答案：美国。\n",
    "追问：皇家赌场的导演是谁？\n",
    "中间答案：《皇家赌场》的导演是马丁·坎贝尔。\n",
    "跟进：马丁·坎贝尔来自哪里？\n",
    "中间答案：新西兰。\n",
    "所以最终的答案是：不会\n",
    "\"\"\",\n",
    "    },\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "3420362f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Question: 乾隆和曹操谁活得更久?\n",
      "\n",
      "这里是否需要跟进问题：是的。\n",
      "追问：乾隆去世时几岁？\n",
      "中间答案：乾隆去世时87岁。\n",
      "追问：曹操去世时几岁？\n",
      "中间答案：曹操去世时66岁。\n",
      "所以最终答案是：乾隆\n",
      "\n"
     ]
    }
   ],
   "source": [
    "example_prompt = PromptTemplate(\n",
    "    input_variables=[\"question\", \"answer\"], template=\"Question: {question}\\n{answer}\"\n",
    ")\n",
    "\n",
    "print(example_prompt.format(**examples[0]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "c61ee4e8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Question: 乾隆和曹操谁活得更久?\n",
      "\n",
      "这里是否需要跟进问题：是的。\n",
      "追问：乾隆去世时几岁？\n",
      "中间答案：乾隆去世时87岁。\n",
      "追问：曹操去世时几岁？\n",
      "中间答案：曹操去世时66岁。\n",
      "所以最终答案是：乾隆\n",
      "\n",
      "\n",
      "Question: 小米手机的创始人什么时候出生?\n",
      "\n",
      "这里是否需要跟进问题：是的。\n",
      "追问：小米手机的创始人是谁？\n",
      "中间答案：小米手机 由 雷军 创立。\n",
      "跟进：雷军什么时候出生？\n",
      "中间答案：雷军出生于 1969 年 12 月 16 日。\n",
      "所以最终的答案是：1969 年 12 月 16 日\n",
      "\n",
      "\n",
      "Question: 乔治·华盛顿的外祖父是谁？\n",
      "\n",
      "这里是否需要跟进问题：是的。\n",
      "追问：乔治·华盛顿的母亲是谁？\n",
      "中间答案：乔治·华盛顿的母亲是玛丽·鲍尔·华盛顿。\n",
      "追问：玛丽·鲍尔·华盛顿的父亲是谁？\n",
      "中间答案：玛丽·鲍尔·华盛顿的父亲是约瑟夫·鲍尔。\n",
      "所以最终答案是：约瑟夫·鲍尔\n",
      "\n",
      "\n",
      "Question: 《大白鲨》和《皇家赌场》的导演是同一个国家的吗？\n",
      "\n",
      "这里是否需要跟进问题：是的。\n",
      "追问：《大白鲨》的导演是谁？\n",
      "中间答案：《大白鲨》的导演是史蒂文·斯皮尔伯格。\n",
      "追问：史蒂文·斯皮尔伯格来自哪里？\n",
      "中间答案：美国。\n",
      "追问：皇家赌场的导演是谁？\n",
      "中间答案：《皇家赌场》的导演是马丁·坎贝尔。\n",
      "跟进：马丁·坎贝尔来自哪里？\n",
      "中间答案：新西兰。\n",
      "所以最终的答案是：不会\n",
      "\n",
      "\n",
      "Question: 李白和白居易谁活得的更久？\n"
     ]
    }
   ],
   "source": [
    "prompt = FewShotPromptTemplate(\n",
    "    examples=examples,\n",
    "    example_prompt=example_prompt,\n",
    "    suffix=\"Question: {input}\",\n",
    "    input_variables=[\"input\"],\n",
    ")\n",
    "\n",
    "print(prompt.format(input=\"李白和白居易谁活得的更久？\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "72343a3e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'这里是否需要跟进问题：是的。\\n追问：李白去世时几岁？\\n中间答案：李白去世时61岁。\\n追问：白居易去世时几岁？\\n中间答案：白居易去世时75岁。\\n所以最终的答案是：白居易活得更久。'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_core.output_parsers import StrOutputParser\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_openai import ChatOpenAI\n",
    "openai_api_key = \"EMPTY\"\n",
    "openai_api_base = \"http://127.0.0.1:1234/v1\"\n",
    "chat = ChatOpenAI(\n",
    "    openai_api_key=openai_api_key,\n",
    "    openai_api_base=openai_api_base,\n",
    "    temperature=0.7,\n",
    ")\n",
    "\n",
    "output_parser = StrOutputParser()\n",
    "\n",
    "chain = prompt | chat | output_parser\n",
    "\n",
    "chain.invoke({\"input\":\"李白和白居易谁活得的更久？\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "2ad097c2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='白居易比李白活得长。白居易出生于772年，去世于846年，享年75岁。而李白出生于701年，去世于762年，只活了62岁。')"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chat.invoke(\"李白和白居易谁活得的更久？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "f1cc594c",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\a4154\\AppData\\Roaming\\Python\\Python310\\site-packages\\transformers\\utils\\hub.py:124: FutureWarning: Using `TRANSFORMERS_CACHE` is deprecated and will be removed in v5 of Transformers. Use `HF_HOME` instead.\n",
      "  warnings.warn(\n",
      "d:\\ProgramData\\anaconda3\\lib\\site-packages\\torch\\_utils.py:776: UserWarning: TypedStorage is deprecated. It will be removed in the future and UntypedStorage will be the only storage class. This should only matter to you if you are using storages directly.  To access UntypedStorage directly, use tensor.untyped_storage() instead of tensor.storage()\n",
      "  return self.fget.__get__(instance, owner)()\n"
     ]
    }
   ],
   "source": [
    "from langchain_community.embeddings.huggingface import HuggingFaceEmbeddings\n",
    "\n",
    "embeddings_path = \"D:\\\\ai\\\\download\\\\bge-large-zh-v1.5\"\n",
    "embeddings = HuggingFaceEmbeddings(model_name=embeddings_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca64c69e",
   "metadata": {},
   "source": [
    "## faiss\n",
    "`faiss` 是一个开源的机器学习库，由Facebook AI Research（FAIR）开发，主要用于高效的大规模向量搜索和聚类。`faiss` 的核心优势在于它为高维向量空间中的数据提供了快速的近似最近邻搜索（ANNS）算法，这对于推荐系统、信息检索、图像和视频分析等应用非常重要。\n",
    "`faiss` 库的主要作用包括：\n",
    "1. **向量搜索**：`faiss` 提供了一系列高效的算法来寻找给定向量集合中与查询向量最接近的向量。这包括基于距离的搜索和基于哈希的搜索方法。\n",
    "2. **聚类**：`faiss` 支持多种聚类算法，如K-means和层次聚类，以及为高维数据优化的聚类方法。\n",
    "3. **特征编码**：`faiss` 包含了一些特征编码方法，如量化和编码，这些方法可以降低数据的维度，同时保持尽可能多的信息。\n",
    "4. **IVF（Inverted File）索引**：`faiss` 实现了一种特殊的索引结构，称为倒排文件索引，这种索引允许快速地搜索大量的高维数据。\n",
    "5. **GPU加速**：`faiss` 库充分利用了NVIDIA GPU的并行计算能力，使得在大规模数据集上的向量搜索和聚类操作变得非常快速。\n",
    "6. **多线程支持**：`faiss` 支持多线程处理，可以进一步提高搜索和聚类的效率。\n",
    "7. **易于使用的API**：`faiss` 提供了Python和C++的API，这些API设计简洁，易于上手和使用。\n",
    "在Python中，你可以通过`faiss`库来实现高效的大规模向量搜索和聚类任务，例如，在处理图像、音频或文本数据时，可以使用`faiss`来快速找到相似的数据点，或者将数据分成具有相似特性的组。这在高维数据处理中是非常有用的，尤其是在需要实时性能的应用中。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ed82d9e",
   "metadata": {},
   "source": [
    "## ChromaDB\n",
    "ChromaDB 是一个开源的、基于 Python 的数据库，专门用于存储和查询时间序列数据。它是由 MongoDB 的创造者开发的一个高性能、可扩展的解决方案，适用于需要处理大规模时间序列数据的场景。ChromaDB 的设计目的是为了提高时间序列数据的查询速度和存储效率，同时保持灵活性和可扩展性。\n",
    "ChromaDB 的主要特点和作用包括：\n",
    "1. **时间序列数据支持**：ChromaDB 专门为时间序列数据设计，可以高效地存储和查询时间戳数据。\n",
    "2. **高性能**：ChromaDB 使用了多种优化技术，如 B-Tree 索引、时间分区等，以提高查询速度和数据写入速度。\n",
    "3. **可扩展性**：ChromaDB 支持水平扩展，可以通过添加更多的服务器来增加存储和处理能力。\n",
    "4. **灵活的数据模型**：虽然 ChromaDB 专为时间序列数据设计，但它也支持文档和键值数据模型，提供了灵活的数据存储选项。\n",
    "5. **丰富的查询功能**：ChromaDB 支持各种查询操作，包括聚合、过滤和排序等，这使得它可以轻松地处理复杂的分析任务。\n",
    "6. **时间索引**：ChromaDB 使用了一种高效的时间索引机制，可以快速地定位到特定时间点或时间范围的数据。\n",
    "7. **时间分区**：ChromaDB 支持时间分区，可以将数据自动或手动分区到不同的集合中，以优化查询性能和存储效率。\n",
    "8. **兼容 MongoDB**：ChromaDB 与 MongoDB 兼容，这意味着你可以使用类似 MongoDB 的 API 来操作 ChromaDB。\n",
    "在 Python 中，ChromaDB 通过其 Python 客户端库提供了一个简单的接口来与数据库进行交互。这使得 Python 开发者可以轻松地将 ChromaDB 集成到他们的应用程序中，以存储、管理和分析时间序列数据。ChromaDB 适用于需要快速、可扩展的时间序列数据存储和查询的各种应用，如监控系统、物联网、金融市场数据分析等。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "ad0d71f1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "与输入最相似的示例: [{'answer': '\\n这里是否需要跟进问题：是的。\\n追问：乾隆去世时几岁？\\n中间答案：乾隆去世时87岁。\\n追问：曹操去世时几岁？\\n中间答案：曹操去世时66岁。\\n所以最终答案是：乾隆\\n', 'question': '乾隆和曹操谁活得更久?'}]\n"
     ]
    }
   ],
   "source": [
    "from langchain.prompts.example_selector import SemanticSimilarityExampleSelector\n",
    "from langchain_community.vectorstores import Chroma\n",
    "\n",
    "\n",
    "example_selector = SemanticSimilarityExampleSelector.from_examples(\n",
    "    # This is the list of examples available to select from.\n",
    "    examples,\n",
    "    # This is the embedding class used to produce embeddings which are used to measure semantic similarity.\n",
    "    embeddings,\n",
    "    # This is the VectorStore class that is used to store the embeddings and do a similarity search over.\n",
    "    Chroma,\n",
    "    # This is the number of examples to produce.\n",
    "    k=1,\n",
    ")\n",
    "\n",
    "# Select the most similar example to the input.\n",
    "question = \"李白和白居易谁活得的更久？\"\n",
    "selected_examples = example_selector.select_examples({\"question\": question})\n",
    "print(f\"与输入最相似的示例: {selected_examples}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "6db373b9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'answer': '\\n这里是否需要跟进问题：是的。\\n追问：乾隆去世时几岁？\\n中间答案：乾隆去世时87岁。\\n追问：曹操去世时几岁？\\n中间答案：曹操去世时66岁。\\n所以最终答案是：乾隆\\n',\n",
       "  'question': '乾隆和曹操谁活得更久?'}]"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "selected_examples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "de3ea25c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'这里是否需要跟进问题：是的。\\n追问：李白去世时几岁？\\n中间答案：李白去世时62岁。\\n追问：白居易去世时几岁？\\n中间答案：白居易去世时75岁。\\n所以最终答案是：白居易'"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "prompt = FewShotPromptTemplate(\n",
    "    example_selector=example_selector,\n",
    "    example_prompt=example_prompt,\n",
    "    prefix=\"根据案例的方式回答问题。\\n\",\n",
    "    suffix=\"Question: {input}\",\n",
    "    input_variables=[\"input\"],\n",
    ")\n",
    "\n",
    "chain = prompt | chat | output_parser\n",
    "\n",
    "chain.invoke({\"input\":\"李白和白居易谁活得的更久？\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f23c44f1",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
